package kayao.client.network.message;

import kayao.client.data.SharedMemory;
import kayao.client.data.Slave;
import kayao.common.Client;
import kayao.common.KayaoValues;
import kayao.common.NetworkUtils;

public class MessageThread extends Thread {

	protected boolean mRunning=true;
	protected boolean mDead=false;
	
	public MessageThread()
	{
		
	}

	public boolean terminate(){
		mRunning = false;
		while(!mDead){
			synchronized(this){
				this.notify();
			}
			System.out.println("[MessageThread] - PROBLEM: STUCK!");
			Thread.yield();
		}
		return false;
	}

	
	public void run()
	{
		System.out.println("### MessageThread started");
		while(mRunning)
		{
			synchronized(this) {
				try {
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			//The notify method is called
			treatHighPriority();
			treatMediumPriority();
			treatLowPriority();
		}
		mDead = true;
	}
	
	/**
	 * Reads a low priority incoming message, treat it and put it in the outgoing queue
	 */
	private void treatLowPriority() {
		IncomingMessage m;
		while((m=MessageHandler.getMessageIncoming(Message.PRIORITY_LOW))!= null)
		{
			System.out.println("[MessageThread] Treating low priority message");
			if(m.getData()[4]==KayaoValues.NEW_MATE_ARRIVED)
			{
				//create the teammate
				Client c=Client.getTeamMateFromMessage(m.getData(),m.getIp());
				System.out.println("[MessageThread] - New teammate arrived in game. Name: "+ c.getName()+ ", ID: "+c.getId());
				SharedMemory.getInstance().addClient(c);
				//Create answer packet
				MessageHandler.insertOutgoingMessage(new WelcomeMessage(
						m.getIp(),2,2,Message.PRIORITY_LOW));
			} 
			else if(m.getData()[4]==KayaoValues.LOGOUT_MSG)
			{
				int client = NetworkUtils.insertByteArrayToInt(m.getData(), 9);
				System.out.println("[MessageThread] - Received logout msg from: "+m.getIp()+" clientid: "+client);
				SharedMemory.getInstance().removeClient(client);
			}
			else if(m.getData()[4]==KayaoValues.TEAM_COMMUNICATION)
			{
				//get the message
				String message=TeamCommunication.getMessage(m);
				//Process it/print it
				System.out.println("[MessageThread] - Incoming message from: "+m.getIp()+": "+ message);
				SharedMemory.getInstance().setIncomingMessage(message);
				//Answer acknowledge
				TeamCommunicationReply tcr=new TeamCommunicationReply(m.getIp(), 3, 5000,
						Message.PRIORITY_LOW,m.getData());
				MessageHandler.insertOutgoingMessage(tcr);
			}
			else if(m.getData()[4]==KayaoValues.TEAM_COMMUNICATION_REPLY)
			{
				//We get the reply
				System.out.println("[MessageThread] - Team message was received by: "+m.getIp());
				MessageHandler.removeAwatingMessage(m);
			}
			else {
				System.out.println("[MessageThread] - Message not treated in Low priority");
			}
		}	
	}
	

	/**
	 * Reads a medium priority incoming message, treat it and put it in the outgoing queue
	 */
	private void treatMediumPriority() {
		IncomingMessage m;
		while((m=MessageHandler.getMessageIncoming(Message.PRIORITY_MEDIUM))!= null)
		{
			if(m.getData()[4]==KayaoValues.SUSCRIPTION_REQUEST)
			{
				System.out.println("[MessageThread] - Received subscription request.");
				SubscriberMessage km= new SubscriberMessage(m.getIp(),3,5000,Message.PRIORITY_MEDIUM,m.getData());
				MessageHandler.insertOutgoingMessage(km);
			} 
			else if(m.getData()[4]==KayaoValues.SUSCRIPTION_REQUEST_ANSWER)
			{
				if(subscriptionRequestIsOld(m))
					continue;
				else
					System.out.println("[MessageThread] - Received list of suscripters.");
				//update subscripters
				SubscriptionRequestMessage.processPacketData(m.getData(), m.getIp());
				//Ask again for them with a delay
				Slave.sendToResponse(m.getIp(),Slave.getKingdomFromIP(m.getIp()));
				//Delete the message from the mResponse queue
				MessageHandler.removeAwatingMessage(m);
			}
			else if(m.getData()[4]==KayaoValues.SUSCRIPTION_REQUEST_NEGATIVE_ANSWER)
			{
				//If it's not the server 
				if(!m.getIp().equals(KayaoValues.SERVER_IP))
				{
					System.out.println("[MessageThread] - Kill old king and look for new one.");
					//Destroy old king
					Slave.removeMyKing(m.getIp()); 
					//Delete the message from the mResponse queue
					MessageHandler.removeAwatingMessage(m);
				}
				else System.out.println("[MessageThread] - New king in empty region. Asking server.");
				//Create new request
				MessageHandler.insertOutgoingMessage(new KingRequestMessage(KayaoValues.SERVER_IP));
			}
			else if(m.getData()[4]==KayaoValues.KING_REQUEST_REPLY_MESSAGE)
			{
				//if it's old skip
				Message msg=null;
				if((msg=isOldKingRequestReply(m))==null)
						continue;
				else System.out.println("[MessageThread] - New Kings List Arrived.");
				//process kings list and send suscriptions request
				if(KingRequestMessage.processPacket(m.getData(), msg))
					Slave.send();
				else System.out.println("[MessageThread] - Kings List didn't change.");
			}
			else System.out.println("[MessageThread] - Message not treated in Medium priority");
		}
	}
	
	private Message isOldKingRequestReply(IncomingMessage m) {
		Message msg=MessageHandler.getAwaitingMessage(m.getCounter());
		//If was already treated it, we skip it
		if(msg==null)
			return null;
		//if it's old we skip it
		if(KingRequestMessage.getLastMessageId()-msg.getMessageId()>1)
		{
			System.out.println("[MessageThread] - Ignoring KingRequestReply for being too old");
			return null;
		}
		return msg;
	}

	private boolean subscriptionRequestIsOld(IncomingMessage m) {
		if(SubscriptionRequestMessage.getLastMessageId()- m.getCounter()>1)
		{
			System.out.println("[MessageThread] - Ignoring Suscription Request for being old");
			return true;
		}
		else return false;
	}

	/**
	 * Reads a high priority incoming message, treat it and put it in the outgoing queue
	 */
	private void treatHighPriority() {
		IncomingMessage m;
		while((m=MessageHandler.getMessageIncoming(Message.PRIORITY_HIGH))!= null)
		{
			if(m.getData()[4]==KayaoValues.STATE_UPDATE)
			{
				//Delete the message from the mResponse queue
				MessageHandler.removeAwatingMessage(m);
				StateUpdateMessage.processPacketData(m.getData());
			}
			else if(m.getData()[4]==KayaoValues.UNSUBSCRIBE_MSG)
			{
				int client = NetworkUtils.insertByteArrayToInt(m.getData(), 9);
				System.out.println("[MessageThread] - Received unsubscribe msg from: "+m.getIp()+" clientid: "+client);
				SharedMemory.getInstance().printSubscribers();
				SharedMemory.getInstance().getKing().removeSlave(client);
				SharedMemory.getInstance().removeSubscriber(client);
				SharedMemory.getInstance().printSubscribers();
			}
			else System.out.println("[MessageThread] - Message not treated in High priority");
		}
		
	}
	
	
}
